package unimelb.filesync.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import unimelb.filesync.common.FileSyncApp;
import unimelb.filesync.common.misc.ArgsValidator;
import unimelb.filesync.common.misc.ProtocolContext;
import unimelb.filesync.common.protocol.IFileSyncPhase;
import unimelb.filesync.common.protocol.ReadPasswordInput;
import unimelb.filesync.server.protocol.AcceptBlockSizeRolePhase;
import unimelb.filesync.server.protocol.CreateKeyPairPhase;
import unimelb.filesync.server.protocol.GetPasswordPhase;
import unimelb.filesync.server.protocol.GetSecretKeyPhase;
import unimelb.filesync.server.protocol.ListenForConnectionPhase;
import unimelb.filesync.server.protocol.PrepareServerFileSync;
import unimelb.filesync.server.protocol.SendPublicKeyPhase;

public class FileSyncServer extends FileSyncApp {

    @Override
    protected Map<String, Object> toParamMap(String[] args) {
        if (args.length != 2) {
            throw new IllegalArgumentException("Invalid arguments. Usage: java -jar syncserver.jar filename port");
        }
        final ArgsValidator validator = new ArgsValidator();
        validator.validatePort(args[1]);

        final Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(ProtocolContext.FILE_NAME, args[0]);
        paramMap.put(ProtocolContext.PORT, Integer.valueOf(args[1]));
        return paramMap;
    }

    @Override
    protected ProtocolContext getProtocolContext() {
        return ProtocolContext.Server;
    }

    @Override
    protected List<IFileSyncPhase> createPhaseList() {
        final List<IFileSyncPhase> phases = new ArrayList<IFileSyncPhase>();
        phases.add(new ReadPasswordInput(getProtocolContext()));
        phases.add(new CreateKeyPairPhase(getProtocolContext()));
        
        phases.add(new ListenForConnectionPhase(getProtocolContext()));
        
        phases.add(new SendPublicKeyPhase(getProtocolContext()));
        phases.add(new GetSecretKeyPhase(getProtocolContext()));
        phases.add(new GetPasswordPhase(getProtocolContext()));
        
        phases.add(new AcceptBlockSizeRolePhase(getProtocolContext()));
        phases.add(new PrepareServerFileSync(getProtocolContext()));
        return phases;
    }

    public static void main(String[] args) {
        try {
            System.out.println("Server is running");
            new FileSyncServer().run(args);
        } catch (Exception e) {
            System.out.println("Exception occurred");
            e.printStackTrace();
            System.exit(1);
        }
    }
}
